【321期】面试官:Java中的拷贝方式,你知道几种?
题外推荐
java数组拷贝主要有四种方法,分别是循环赋值
,System.arraycopy()
,Arrays.copyOf()
(或者Arrays.copyOfRange)和clone()
方法。
循环拷贝
循环拷贝其实没什么好说的啦,就是用一个for循环进行元素的逐个拷贝,是浅拷贝,拷贝速度比较慢;
实例代码:
import java.util.Arrays;
//for循环拷贝数组
public class KaoBei2 {//一维数组的拷贝
public static void main(String[] args) {
// TODO 自动生成的方法存根
int[] array1={1,2,3,4,5,6,7};
int[] array2=new int[array1.length];
for(int i = 0;i < array1.length;i++){
array2[i] = array1[i];
}
System.out.println(Arrays.toString(array2));
//二维数组的拷贝
int[][] array3= {{1,2,3},{4,5,6}};
int[][] array4 = new int[2][3];
for(int i = 0;i < array3.length;i++){
for(int j = 0;j < array3[i].length;j++){
array4[i][j] = array3[i][j];
}
}
System.out.println(Arrays.deepToString(array4));
}
}
运行结果:
System.arraycopy(浅拷贝)
这个是系统提供的拷贝方式,它是浅拷贝,也就是说对于非基本类型而言,它拷贝的是对象的引用,而不是去新建一个新的对象。通过它的代码我们可以看到,这个方法不是用java语言写的,而是底层用c或者c++实现的,因而速度会比较快。
public static native void arraycopy(Object src, int srcPos,Object dest, int destPos,int length);
通过源代码我们可以看到,关键字native说明它不是用java语言写的,而是调用其他语言的代码。往期:300期面试题
实例代码:
import java.util.Arrays;
//System.arraycopy 相对较快的拷贝方式 native 方法
public class kaoBei1 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//一维数组的拷贝
int[] array = {1,2,3,4,5};
int[] array2 = new int[array.length];
System.arraycopy(array, 0, array2, 0, array.length);//(被复制的数组,从几号下标开始复制,复制到哪个数组,复制到新数组第几号下标,复制长度)
System.out.println(Arrays.toString(array2));
//二维数组的拷贝
int[][] array1={{1,2,3,5,9},{2,3,36,5,7}};
int[][] array3=new int[2][5];
for(int i=0;i<array1.length;i++){
System.arraycopy(array1[i], 0, array3[i], 0, array1[i].length);
}
System.out.println(Arrays.deepToString(array3));
}
}
运行结果:
Arrays.copyOf(浅拷贝)
这个方法也是浅拷贝,我们看一下它的源代码就知道了。
public static byte[] copyOfRange(byte[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
byte[] copy = new byte[newLength];
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}
实际上它调用的就是System.arraycopy
,所以肯定也是浅拷贝。
实例代码:
import java.util.Arrays;
//Array.copyOf拷贝数组
public class KaoBei4 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//一维数组的拷贝
int[] array=new int[4];
System.out.println(Arrays.toString(array));
int[] array1 = new int[4];
array1 = Arrays.copyOf(array,array.length);//将数组array拷贝到数组brr,拷贝长度为array.length
System.out.println(Arrays.toString(array1));
//一维数组的拷贝
int[][] array2={{1,2,3,4},{2,6,7,5}};
int[][] array3=new int[2][4];
array3=Arrays.copyOf(array2, array2.length);
System.out.println(Arrays.deepToString(array3));
}
}
运行结果:
Object.clone
clone()
比较特殊,对于对象而言,它是深拷贝,但是对于数组而言,它是浅拷贝。
实例代码:
import java.util.Arrays;
//clone拷贝数组
public class KaoBei3 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//一维数组的拷贝
int[] array1={1,2,3,5,9,8,7};
int[] array2=new int[array1.length];
array2=array1.clone();
System.out.println(Arrays.toString(array2));
//二维数组的拷贝
int[][] array3={{1,2,3,4},{5,6,7}};
int[][] array4=new int[2][];
for(int i = 0;i < array3.length;i++){
array4[i] = array3[i].clone();
}
for(int i=0;i<array3.length;i++){
System.out.print(Arrays.toString(array4[i]));
}
}
}
运行结果:
对象拷贝
首先讲一下对象的拷贝,它是深拷贝,大家可以用对象去测试一下。下面我们看一下它的源代码:
protected native Object clone() throws CloneNotSupportedException;
这里也有native关键字,所以也是底层的c语言实现的。
还要注意的是,这里修饰符是protected,也就是说,我们创建了一个Object类以后,是不能直接调用这个clone()方法的,因为protected关键字只允许同一个包内的类和它的子类调用,所以我们声明一个object类时,肯定不是同一个包内,所以就不能去调用它。
要调用这个方法,就需要我们写一个类,然后声明实现cloneable接口就好了,不需要去显示地声明继承于object,因为java中的类如果不显示说明父类的话,默认父类就是object。然后我们继承这个方法:
public Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
这里需要是,为了能够在不同包内去调用这个方法,我们需要把这个权限升级为public。现在我们就可以调用这个类的clone()
方法去拷贝我们的类了。往期:300期面试题
数组拷贝
对于数组而言,它不是简单的将引用赋值为另外一个数组引用,而是创建一个新的数组。但是我们知道,对于数组本身而言,它它的元素是对象的时候,本来数组每个元素中保存的就是对象的引用,所以,拷贝过来的数组自然而言也是对象的引用,所以对于数组对象元素而言,它又是浅拷贝。我们用以下代码验证一下:
class Aby implements Cloneable{
public int i;
public Aby(int i) {
this.i = i;
}
@Override
public Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
public class Solution {
public static void main(String[] args) throws CloneNotSupportedException {
Aby aby1 = new Aby(1);
Aby aby2 = (Aby) aby1.clone();
aby1.i = 2;
System.out.println(aby1.i); //2
System.out.println(aby2.i); //1
Aby[] arr = {aby1,aby2};
Aby[] arr2 = arr.clone();
arr2[0].i = 3;
System.out.println(arr[0].i); //3
System.out.println(arr2[0].i); //3
}
}
感谢阅读,希望对你有所帮助 :)
来源:blog.csdn.net/qq_36883748/article/details/79950993
END
●【301期】面试官:dubbo为什么没有采用jdk的spi机制?
●【305期】面试官:Redis用过是吧?那你讲讲Redis都有哪些监控指标?
与其在网上拼命找题? 不如马上关注我们~
PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!